tree grammar PascalVisitor;
options{
  tokenVocab=Pascal;
  ASTLabelType=PascalNode;
}
@header{
  package com.lifesting.book.wci;
  
  import wci.intermediate.*;
  import wci.intermediate.symtabimpl.SymTabKeyImpl;
}
@members{
  protected SymTabStack symtabStack = SymTabFactory.createSymTabStack();
  public SymTabStack getSymbolTableStack(){
    return this.symtabStack;
  }
}
program	: 
  compound;
compound :
  ^(COMPOUND stmt+);
stmt:
  compound | assign;
assign:
  ^(ASSIGN i=ID e=expr){
    String var = $i.text.toLowerCase();
    SymTabEntry id_entry = symtabStack.lookup(var) ;
    if (id_entry == null)
    {
      id_entry = symtabStack.enterLocal(var);
    }
    id_entry.setAttribute(SymTabKeyImpl.DATA_VALUE,e);
  };
expr returns[Object value]:
  s=simple{value=s;} 
  | ^(r=rel_ops e1=expr e2=expr){
    if (e1 instanceof Number && e2 instanceof Number){
      double de1 = ((Number)e1).doubleValue();
      double de2 = ((Number)e2).doubleValue();
      switch (r){
        case 1:
          value = de1 < de2;
          break;
        case 2:
          value = de1 <= de2;
          break;
        case 3:
          value = de1 > de2;
          break;
        case 4:
          value = de1 >= de2;
          break;
        case 5:
          value = de1 != de2;
          break;
        default:
          break;
      }
    }else{
      System.err.println("无法执行比较:"+e1+"["+r+"]"+e2);
    }
  };
simple returns[Object value]:
  s=term{value=s;} 
  | ^(o=add_ops f1=negterm f2=simple) 
  {
    double df1 = Double.parseDouble(f1.toString());
    if (f2 instanceof Number){
      double df2 = Double.parseDouble(f2.toString());
      switch (o)
      {
        case 1:
          value = df1+df2;
          break;
        case 2:
          value = df1-df2;
          break;
      }
    }else{
      System.err.println("不是一个数值:"+f2);
    }
  }
  | ^(o=add_ops f1=simple f2=simple){
     if (f1 instanceof Number && f2 instanceof Number){
        double df1 = Double.parseDouble(f1.toString());
        double df2 = Double.parseDouble(f2.toString());
        switch (o){
          case 1:
            value = df1+df2;
            break;
          case 2:
            value = df1-df2;
            break;
          default:
            break;
        }
     }else if (f1 instanceof Boolean && f2 instanceof Boolean){
       value= ((Boolean)f1).booleanValue() || ((Boolean)f2).booleanValue();
     }else{
       System.err.println("不能执行simple运算,f1="+f1+",f2="+f2);
     }
  };
  
  
negterm returns[Object value]:
  ^(NEGATE n=term) {
    if(n instanceof Number){
      return -Double.parseDouble(n.toString());
    }else{
      System.err.println("不是一个数值:"+n);
      value = 0.0;
    }
  };
  
term returns[Object value]:
  f0=factor{value=f0;} 
  | ^(t=mul_ops f1=factor f2=factor){
    if (f1 instanceof Number && f2 instanceof Number){
      double df1 = Double.parseDouble(f1.toString());
      double df2 = Double.parseDouble(f2.toString());
      switch (t){
        case 1:
          value= df1*df2;
          break;
        case 2:
        case 3:
          value= df1/df2;
        case 4:
          value=df1 \% df2;
        default:
          break;
      }
    }else if (f1 instanceof Boolean && f2 instanceof Boolean){
      value= ((Boolean)f1).booleanValue() && ((Boolean)f2).booleanValue();
    }else{
      System.err.println("不能执行term运算,f1="+f1+",f2="+f2);
    }
  };
  
factor returns[Object value]:
  i = ID{
    String var = $i.text.toLowerCase();
    SymTabEntry id_entry = symtabStack.lookup(var);
    if (id_entry == null){
      System.err.println("使用不存在的变量:"+var);
    }else{
      value = id_entry.getAttribute(SymTabKeyImpl.DATA_VALUE);
    }
  } 
  | n=NUMBER{value =((PascalAntlrToken)$n.getToken()).getValue();} 
  | r=NUMBER_REAL{value = ((PascalAntlrToken)$r.getToken()).getValue();}
  | s=STRING {value =((PascalAntlrToken)$s.getToken()).getValue(); }
  | ^(NOT f=factor) { 
      if (f instanceof Boolean){
        value = !((Boolean)f).booleanValue();
      }else{
        System.err.println("不是一个布尔值:"+f);
      }
    }
  
  | ^(NESTEXPR e = expr){
      value = e;
    }; 
  
rel_ops returns [int type]:
  LT{type =1;} | LE{type = 2;} | GT{type=3;} | GE{type=4;} | NOT_EQUAL{type=5;};
add_ops returns [int type]:
  PLUS{type=1;} | MINUS{type=2;} | OR{type=3;}; 
mul_ops returns [int type]:
  STAR{type = 1;} | SLASH{type=2;} | DIV{type=3;} | MOD{type=4;} | AND{type=5;};
